from typing import Optional, Union
from uuid import UUID

from core.models import convert_to_uuid
from apps.app_auth_provider.models import InternalUser, ExternalUser


class InternalUserManager:
    @staticmethod
    def get_internal_user_by_email(email: str) -> Optional[InternalUser]:
        return InternalUser.objects.filter(email=email).first()

    @staticmethod
    def get_internal_user(user_id: Union[str, UUID]) -> Optional[InternalUser]:
        user_id = convert_to_uuid(user_id)
        if user_id is None:
            return None

        return InternalUser.objects.filter(id=user_id).first()

    @staticmethod
    def create_internal_user(
            email: str,
            true_name: str,
            org_name: str,
            is_active: bool = True,
            description: str = ''
    ) -> InternalUser:
        user = InternalUser(
            email=email,
            true_name=true_name,
            org_name=org_name,
            is_active=is_active,
            description=description
        )
        user.save(force_insert=True)
        return user


class ExternalUserManager:
    @staticmethod
    def get_external_user(provider_type: str, external_id: str) -> Optional[ExternalUser]:
        return ExternalUser.objects.select_related('internal_user').filter(
            external_id=external_id,
            provider_type=provider_type
        ).first()

    @staticmethod
    def get_external_user_by_id(u_id: Union[str, UUID]) -> Optional[ExternalUser]:
        u_id = convert_to_uuid(u_id)
        if u_id is None:
            return None

        return ExternalUser.objects.select_related('internal_user').filter(
            id=u_id,
        ).first()

    @staticmethod
    def create_external_user(
            provider_type: str,
            external_id: str,
            email: str,
            true_name: str,
            org_name: str,
            internal_user: Optional[InternalUser] = None
    ) -> ExternalUser:
        user = ExternalUser(
            provider_type=provider_type,
            external_id=external_id,
            email=email,
            true_name=true_name,
            org_name=org_name,
            internal_user=internal_user
        )
        user.save(force_insert=True)
        return user
